from typing import Optional, List, Tuple, Dict, Any
from datetime import datetime, timedelta
from tortoise.functions import Count, Avg
from app.modules.logs.models import OperationLogModel
from app.modules.logs.schemas import (
    OperationLogInfo, LogQueryParams, LogStatistics, LogExportParams
)
from app.core.exceptions import BusinessException


class LogService:
    """日志服务类"""

    @staticmethod
    async def get_log_list(
        skip: int = 0, 
        limit: int = 50,
        query_params: Optional[LogQueryParams] = None
    ) -> Tuple[int, List[OperationLogInfo]]:
        """获取日志列表（带分页和查询条件）"""
        query = OperationLogModel.all()
        
        # 应用查询条件
        if query_params:
            if query_params.username:
                query = query.filter(username__icontains=query_params.username)
            if query_params.module:
                query = query.filter(module__icontains=query_params.module)
            if query_params.action:
                query = query.filter(action__icontains=query_params.action)
            if query_params.method:
                query = query.filter(method=query_params.method)
            if query_params.ip:
                query = query.filter(ip__icontains=query_params.ip)
            if query_params.success is not None:
                query = query.filter(success=query_params.success)
            if query_params.status_code:
                query = query.filter(status_code=query_params.status_code)
            if query_params.start_time:
                query = query.filter(created_at__gte=query_params.start_time)
            if query_params.end_time:
                query = query.filter(created_at__lte=query_params.end_time)
        
        total = await query.count()
        logs = await query.offset(skip).limit(limit).order_by('-created_at')
        
        # 转换为Pydantic模型
        log_info_list = [OperationLogInfo.from_orm(log) for log in logs]
        return total, log_info_list

    @staticmethod
    async def get_log_by_id(log_id: int) -> Optional[OperationLogInfo]:
        """根据ID获取日志详情"""
        log = await OperationLogModel.get_or_none(id=log_id)
        if not log:
            return None
        return OperationLogInfo.from_orm(log)

    @staticmethod
    async def get_user_logs(user_id: int, limit: int = 50) -> List[OperationLogInfo]:
        """获取用户操作日志"""
        logs = await OperationLogModel.get_user_logs(user_id, limit)
        return [OperationLogInfo.from_orm(log) for log in logs]

    @staticmethod
    async def get_module_logs(module: str, limit: int = 50) -> List[OperationLogInfo]:
        """获取模块操作日志"""
        logs = await OperationLogModel.get_module_logs(module, limit)
        return [OperationLogInfo.from_orm(log) for log in logs]

    @staticmethod
    async def get_error_logs(limit: int = 50) -> List[OperationLogInfo]:
        """获取错误日志"""
        logs = await OperationLogModel.get_error_logs(limit)
        return [OperationLogInfo.from_orm(log) for log in logs]

    @staticmethod
    async def get_log_statistics() -> LogStatistics:
        """获取日志统计信息"""
        # 总日志数
        total_logs = await OperationLogModel.all().count()
        
        # 成功和错误日志数
        success_logs = await OperationLogModel.filter(success=True).count()
        error_logs = await OperationLogModel.filter(success=False).count()
        
        # 今日日志数
        today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        today_logs = await OperationLogModel.filter(created_at__gte=today).count()
        
        # 平均执行时长
        avg_duration_result = await OperationLogModel.all().annotate(
            avg_duration=Avg('duration')
        ).first()
        avg_duration = avg_duration_result.avg_duration if avg_duration_result.avg_duration else 0.0
        
        # 热门模块（按操作次数排序）
        top_modules_result = await OperationLogModel.all().annotate(
            count=Count('id')
        ).group_by('module').order_by('-count').limit(10)
        
        top_modules = [
            {
                'module': item.module,
                'count': item.count
            } for item in top_modules_result
        ]
        
        # 活跃用户（按操作次数排序）
        top_users_result = await OperationLogModel.all().annotate(
            count=Count('id')
        ).group_by('username').order_by('-count').limit(10)
        
        top_users = [
            {
                'username': item.username,
                'count': item.count
            } for item in top_users_result
        ]
        
        return LogStatistics(
            total_logs=total_logs,
            success_logs=success_logs,
            error_logs=error_logs,
            today_logs=today_logs,
            avg_duration=round(avg_duration, 3),
            top_modules=top_modules,
            top_users=top_users
        )

    @staticmethod
    async def get_recent_logs(hours: int = 24) -> List[OperationLogInfo]:
        """获取最近N小时的日志"""
        start_time = datetime.now() - timedelta(hours=hours)
        logs = await OperationLogModel.filter(created_at__gte=start_time).order_by('-created_at')
        return [OperationLogInfo.from_orm(log) for log in logs]

    @staticmethod
    async def get_logs_by_time_range(
        start_time: datetime, 
        end_time: datetime
    ) -> List[OperationLogInfo]:
        """获取指定时间范围的日志"""
        logs = await OperationLogModel.filter(
            created_at__gte=start_time,
            created_at__lte=end_time
        ).order_by('-created_at')
        return [OperationLogInfo.from_orm(log) for log in logs]

    @staticmethod
    async def delete_old_logs(days: int = 30) -> int:
        """删除指定天数之前的日志"""
        cutoff_date = datetime.now() - timedelta(days=days)
        deleted_count = await OperationLogModel.filter(created_at__lt=cutoff_date).delete()
        return deleted_count

    @staticmethod
    async def clear_all_logs() -> int:
        """清空所有日志"""
        deleted_count = await OperationLogModel.all().delete()
        return deleted_count

    @staticmethod
    async def export_logs(export_params: LogExportParams) -> List[Dict[str, Any]]:
        """导出日志数据"""
        query = OperationLogModel.all()
        
        # 应用导出条件
        if export_params.start_time:
            query = query.filter(created_at__gte=export_params.start_time)
        if export_params.end_time:
            query = query.filter(created_at__lte=export_params.end_time)
        if export_params.modules:
            query = query.filter(module__in=export_params.modules)
        if export_params.success_only:
            query = query.filter(success=True)
        
        logs = await query.order_by('-created_at')
        
        # 转换为导出格式
        export_data = []
        for log in logs:
            export_data.append({
                'id': log.id,
                'username': log.username,
                'module': log.module,
                'action': log.action,
                'method': log.method,
                'path': log.path,
                'ip': log.ip,
                'status_code': log.status_code,
                'duration': log.duration,
                'success': log.success,
                'error_message': log.error_message,
                'created_at': log.created_at.strftime('%Y-%m-%d %H:%M:%S')
            })
        
        return export_data

    @staticmethod
    async def get_log_summary() -> Dict[str, Any]:
        """获取日志摘要信息"""
        # 今日统计
        today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        today_total = await OperationLogModel.filter(created_at__gte=today).count()
        today_success = await OperationLogModel.filter(created_at__gte=today, success=True).count()
        today_error = await OperationLogModel.filter(created_at__gte=today, success=False).count()
        
        # 本周统计
        week_ago = datetime.now() - timedelta(days=7)
        week_total = await OperationLogModel.filter(created_at__gte=week_ago).count()
        
        # 本月统计
        month_ago = datetime.now() - timedelta(days=30)
        month_total = await OperationLogModel.filter(created_at__gte=month_ago).count()
        
        return {
            'today': {
                'total': today_total,
                'success': today_success,
                'error': today_error
            },
            'week': {
                'total': week_total
            },
            'month': {
                'total': month_total
            }
        } 